package com.cskaoyan.wordmemorize.service.impl.app;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.converter.PayConverter;
import com.cskaoyan.wordmemorize.dao.entity.UserDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocBoundLogDO;
import com.cskaoyan.wordmemorize.dao.entity.UserVocBoundStatisticsDO;
import com.cskaoyan.wordmemorize.dao.entity.VocPaySaleDO;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.PayOrderDTO;
import com.cskaoyan.wordmemorize.dto.app.VocPaySaleDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.PaySuccessNotifyCommand;
import com.cskaoyan.wordmemorize.request.VocPaySaleCommand;
import com.cskaoyan.wordmemorize.service.UserPayService;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class UserPayServiceImpl implements UserPayService {

    @Autowired
    VocPaySaleMapper userPaySaleMapper;

    @Autowired
    PayConverter payConverter;

    @Autowired
    GoodsMapper goodsMapper;
    @Autowired
    private UserVocBoundLogMapper userVocBoundLogMapper;
    @Autowired
    private UserMapper userMapper;

    // voc_pay_sale表

    // 1.APP支付接口(解锁等级，购买代词上限, 购买补签卡)
    @Override
    public PayOrderDTO pay(VocPaySaleCommand command, Long userId) {
        // TODO
        // 1.创建支付交易记录
        command.setUserId(userId.toString());
        VocPaySaleDO vocPaySaleDO = payConverter.vocPaySaleCommand2DO(command);
        userPaySaleMapper.insert(vocPaySaleDO);
        // 2.根据paySaleId查询出paySaleDO
        // 3.根据paySaleDO生成支付订单
        if (vocPaySaleDO != null) {
            PayOrderDTO payOrderDTO = payConverter.vocPaySaleDO2PayOrderDTO(vocPaySaleDO);
            return payOrderDTO;
        }
        return null;
    }

    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;

    // 2.支付成功接口，我需要我们自己通过postman或者Api Fox模拟支付成功的通知(解锁等级，购买代词上限, 购买补签卡)
    @Override
    @Transactional
    public String paySuccess(PaySuccessNotifyCommand command, Long userId) {
        // 后端接收到支付宝或者微信的支付通知后，修改支付交易状态
        // 1.根据paySaleId查询出paySaleDO
        UpdateWrapper<VocPaySaleDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id",command.getId())
                .eq("user_id",userId)
                .set("status",command.getTradeStatus());
        userPaySaleMapper.update(updateWrapper);

        // 请求通知中会携带所支付的支付交易id，根据支付交易id查询voc_pay_sale，我们可以知道交易类型
        VocPaySaleDO vocPaySaleDO = userPaySaleMapper.selectById(command.getId());
        // 交易类型
        Integer itemType = vocPaySaleDO.getItemType();
        // 商品id
        Long itemId = vocPaySaleDO.getItemId();
        // 单词上限：1
        // 查询goods表中对应的(单词上限增加量,解锁等级数)
        Integer value = goodsMapper.selectById(itemId).getValue();


        String ret = getPayReslut(command, userId, itemType, value);

        return ret;
    }

    private String getPayReslut(PaySuccessNotifyCommand command, Long userId, Integer itemType, Integer value) {
        if (itemType == 1){
            // 修改voc_bound_statistics，并且向voc_bound_log中新增一条单词上限变更记录
            UpdateWrapper<UserVocBoundStatisticsDO> updateWrapper1 = new UpdateWrapper<>();
            // 获取当前时间
            updateWrapper1.eq("user_id", userId)
                    .setSql("pay = pay + " + value)
                    .setSql("total = total + " + value)
                    .setSql("available = available + " + value)
                    .setSql("updated_time = " + LocalDateTime.now());
            userVocBoundStatisticsMapper.update(updateWrapper1);

            // 向voc_bound_log中新增一条单词上限变更记录
            UserVocBoundLogDO userVocBoundLogDO = new UserVocBoundLogDO();
            userVocBoundLogDO.setUserId(userId);
            userVocBoundLogDO.setPaySaleId(command.getId());
            userVocBoundLogDO.setLogDate(LocalDate.now());
            userVocBoundLogDO.setType(1);
            userVocBoundLogDO.setCount(value);
            userVocBoundLogDO.setDescription("购买单词上限");
            userVocBoundLogMapper.insert(userVocBoundLogDO);
            return "购买单词上限成功";

        }
        // 等级解锁：2
        // 则修改用户的等级，以及升级时间(修改user表)
        else if (itemType == 2){
            UpdateWrapper<UserDO> updateWrapper3 = new UpdateWrapper<>();
            updateWrapper3.eq("id", userId)
                    .setSql("level_name = " + "LVL" + value)
                    .setSql("level_value = " + value)
                    .setSql("level_time = " + LocalDateTime.now());
            userMapper.update(updateWrapper3);
            return "用户等级升级成功";
        }

        // 补签卡：3
        // 若无补签卡，则修user表，设置用户位有补签卡的状态
        // 若有补签卡，一个用户不允许购买多张补签卡
        else if (itemType == 3){
            // 查询user表中是否有补签卡
            Integer hasSignCard = userMapper.selectById(userId).getHasSignCard();
            if (hasSignCard == 0){
                UpdateWrapper<UserDO> updateWrapper4 = new UpdateWrapper<>();
                updateWrapper4.eq("id", userId)
                       .setSql("has_sign_card = 1");
                userMapper.update(updateWrapper4);
            }
            else {
                return "您已经有补签卡了";
            }
        }
        return null;
    }


    // 3.APP获取支付结果*
    @Override
    public Integer queryTradeStatus(Long paySaleId) {
        // 在表中查询paySaleId对应的payStatus
        QueryWrapper<VocPaySaleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",paySaleId);
        Integer status = userPaySaleMapper.selectOne(queryWrapper).getStatus();
        return status;
    }

    // 4.APP获取购买历史**
    @Override
    public PageDTO<VocPaySaleDTO> getPaySaleHistory(Long userId, PageRequest pageRequest) {

        Page<VocPaySaleDO> vocPaySaleDOPage = new Page<>(pageRequest.getPageNum(),pageRequest.getCount());
        QueryWrapper<VocPaySaleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        List<VocPaySaleDO> records
                = userPaySaleMapper.selectPage(vocPaySaleDOPage, queryWrapper).getRecords();
        long total = userPaySaleMapper.selectCount(queryWrapper);

        // DO -> DTO
        PageDTO<VocPaySaleDTO> vocPaySaleDTOPageDTO = payConverter.vocPaySalePage2PageDTO(records, total);

        return vocPaySaleDTOPageDTO;
    }
}
